package service

import (
	"context"
	"crypto/ecdsa"
	"errors"

	"reward-server/global"
	"reward-server/service/eth"

	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/spf13/cast"
	"go.uber.org/zap"
)

type IWishService interface {
	Number() (int64, error)
	Owner() (string, error)
	GetAddressToAmountFunded(addr string) (int64, error)
	GetBalance(addr string) (any, error)
	Withdraw() (string, error)
}

type WishService struct {
	Contract   *eth.Eth
	privateKey string
}

func NewWishService() IWishService {
	cfg := global.ServerConfig.Eth
	contractAddress := common.HexToAddress(cfg.WishAddr)
	contract, _ := eth.NewEth(contractAddress, global.Ethclient)

	return &WishService{
		Contract:   contract,
		privateKey: cfg.PrivateKey,
	}
}

// Number 获取许愿人数
func (w *WishService) Number() (int64, error) {

	num, err := w.Contract.Number(new(bind.CallOpts))
	return cast.ToInt64(num), err
}

// Owner 获取合约所有者
func (w *WishService) Owner() (string, error) {

	addr, err := w.Contract.GetOwner(new(bind.CallOpts))
	if err != nil {
		return "", err

	}
	return addr.String(), err
}

// GetAddressToAmountFunded  获取许愿者当前许愿金额
func (w *WishService) GetAddressToAmountFunded(addr string) (int64, error) {

	//用户地址
	account := common.HexToAddress(addr)

	blance, err := w.Contract.GetAddressToAmountFunded(new(bind.CallOpts), account)
	if err != nil {
		return 0, err
	}

	return cast.ToInt64(blance), err
}

// 获取钱包剩余金额
func (w *WishService) GetBalance(addr string) (any, error) {

	account := common.HexToAddress(addr)
	balance, err := global.Ethclient.BalanceAt(context.Background(), account, nil)
	if err != nil {
		return nil, err
	}
	return balance, nil
}

func (w *WishService) Withdraw() (string, error) {

	// 1. 解析管理员私钥
	privateKey, err := crypto.HexToECDSA(w.privateKey)
	if err != nil {
		zap.S().Infof("Invalid private key: %v", err)
		return "", err
	}

	// 2. 获取管理员地址
	fromAddress, err := GetAddressFromPrivateKey(privateKey)
	if err != nil {
		zap.S().Errorf("Failed to get address from private key: %v", err)
		return "", err
	}

	// 3. 获取链 ID（如 Sepolia、Goerli 等）
	chainID, err := global.Ethclient.ChainID(context.Background())
	if err != nil {
		zap.S().Errorf("Failed to get chain ID: %v", err)
		return "", err
	}

	// 4. 创建 TransactOpts
	auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID)
	if err != nil {
		zap.S().Errorf("Failed to create transaction opts: %v", err)
		return "", err
	}
	auth.From = fromAddress

	// 5. 设置 Gas Limit（可选，如果不设置会自动估算）
	auth.GasLimit = 300000 // 根据合约操作复杂度适当调整

	// 6. 调用智能合约的 Withdraw 函数
	tx, err := w.Contract.Withdraw(auth)
	if err != nil {
		zap.S().Errorf("Failed to invoke Withdraw: %v", err)
		return "", err
	}

	// 7. 返回交易哈希供后续查询
	return tx.Hash().Hex(), nil
}

// GetAddressFromPrivateKey 生成账号地址
func GetAddressFromPrivateKey(privateKey *ecdsa.PrivateKey) (common.Address, error) {
	publicKey := privateKey.Public()
	publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
	if !ok {
		return common.Address{}, errors.New("error casting public key to ECDSA")
	}

	address := crypto.PubkeyToAddress(*publicKeyECDSA)
	zap.S().Infof("address=%s\n", address)
	return address, nil
}
